home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 32 / Mac Magazin and MacEasy Magazine CD - Issue 32.iso / Multimedia / PlayerPRO 4.5.5 Dev.Kit / Plug-Ins / Music Import⁄Export Plugs / Mod.c < prev    next >
Text File  |  1997-02-25  |  24KB  |  888 lines

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.5x -- MOD to MADx & MADx to MOD
  4. //
  5. //    Version 1.0    - 12.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:        100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "RDriver.h"
  21. #include "MOD.h"
  22. #include "FileUtils.h"
  23.  
  24. #ifdef _MAC_H
  25. #if defined(powerc) || defined(__powerc)
  26. enum {
  27.         PlayerPROPlug = kCStackBased
  28.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  29.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  30.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr)))
  31.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  32.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  33.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( MADDriverSettings*)))
  34. };
  35.  
  36. ProcInfoType __procinfo = PlayerPROPlug;
  37. #else
  38. #include <A4Stuff.h>
  39. #endif
  40. #endif
  41.  
  42. debugger(Ptr);
  43.  
  44. short FoundNote( short Period)
  45. {
  46. short             note;
  47. short                MODTuning[ 65] =
  48. {
  49.  
  50. // -> Tuning 0
  51.  
  52.     1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  53.     856,808,762,720,678,640,604,570,538,508,480,453,
  54.     428,404,381,360,339,320,302,285,269,254,240,226,
  55.     214,202,190,180,170,160,151,143,135,127,120,113,
  56.     107,101,95,90,85,80,75,71,67,63,60,56
  57. };
  58.     note = 0xFF;
  59.     
  60.     
  61.     if(Period != 0)
  62.     {
  63.         for(note = 0;note < 60;note++)
  64.         {
  65.             if(Period >= MODTuning[ note]) break;
  66.         }
  67.         if(note >= NUMBER_NOTES) note = 0xFF;
  68.     }
  69.     
  70.     if( note != 0xFF) note += 24;
  71.     
  72.     return note;
  73. }
  74.  
  75. Cmd* GetMADCommand( register short PosX, register short    TrackIdX, register PatData*    tempMusicPat)
  76. {
  77.     if( PosX < 0) PosX = 0;
  78.     else if( PosX >= tempMusicPat->header.size) PosX = tempMusicPat->header.size -1;
  79.         
  80.     return( & (tempMusicPat->Cmds[ (tempMusicPat->header.size * TrackIdX) + PosX]));
  81. }
  82.  
  83. Ptr MADNewPtr( long size, MADDriverSettings* init)
  84. {
  85.     if( init->sysMemory) return NewPtrSys( size);
  86.     else return NewPtr( size);
  87. }
  88.  
  89. Ptr MADNewPtrClear( long size, MADDriverSettings* init)
  90. {
  91.     if( init->sysMemory) return NewPtrSysClear( size);
  92.     else return NewPtrClear( size);
  93. }
  94.  
  95. void AnalyseSignatureMOD( long EOFo, long temp, short *maxInstru, long *PatternSize, short *tracksNo, MODDef* aMOD)
  96. {
  97.     long         test, i;
  98.     Boolean        result;
  99.     
  100.     *maxInstru = 31;
  101.     
  102.     MOT32( &temp);
  103.     
  104.     switch( temp)
  105.     {
  106.         case 'FLT4':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  107.         case 'FLT8':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  108.         case 'M.K.':    *PatternSize = sizeof( struct MODCom) * 64L * 4L;    *tracksNo = 4;    break;
  109.         case '5CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 5L;    *tracksNo = 5;    break;
  110.         case '6CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 6L;    *tracksNo = 6;    break;
  111.         case '7CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 7L;    *tracksNo = 7;    break;
  112.         case '8CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 8L;    *tracksNo = 8;    break;
  113.         case '9CHN':    *PatternSize = sizeof( struct MODCom) * 64L * 9L;    *tracksNo = 9;    break;
  114.         case '10CH':    *PatternSize = sizeof( struct MODCom) * 64L * 10L;    *tracksNo = 10;    break;
  115.         case '11CH':    *PatternSize = sizeof( struct MODCom) * 64L * 11L;    *tracksNo = 11;    break;
  116.         case '12CH':    *PatternSize = sizeof( struct MODCom) * 64L * 12L;    *tracksNo = 12;    break;
  117.         case '13CH':    *PatternSize = sizeof( struct MODCom) * 64L * 13L;    *tracksNo = 13;    break;
  118.         case '14CH':    *PatternSize = sizeof( struct MODCom) * 64L * 14L;    *tracksNo = 14;    break;
  119.         case '15CH':    *PatternSize = sizeof( struct MODCom) * 64L * 15L;    *tracksNo = 15;    break;
  120.         case '16CH':    *PatternSize = sizeof( struct MODCom) * 64L * 16L;    *tracksNo = 16;    break;
  121.         case '17CH':    *PatternSize = sizeof( struct MODCom) * 64L * 17L;    *tracksNo = 17;    break;
  122.         case '18CH':    *PatternSize = sizeof( struct MODCom) * 64L * 18L;    *tracksNo = 18;    break;
  123.         case '19CH':    *PatternSize = sizeof( struct MODCom) * 64L * 19L;    *tracksNo = 19;    break;
  124.         case '20CH':    *PatternSize = sizeof( struct MODCom) * 64L * 20L;    *tracksNo = 20;    break;
  125.         case '21CH':    *PatternSize = sizeof( struct MODCom) * 64L * 21L;    *tracksNo = 21;    break;
  126.         case '22CH':    *PatternSize = sizeof( struct MODCom) * 64L * 22L;    *tracksNo = 22;    break;
  127.         case '23CH':    *PatternSize = sizeof( struct MODCom) * 64L * 23L;    *tracksNo = 23;    break;
  128.         case '24CH':    *PatternSize = sizeof( struct MODCom) * 64L * 24L;    *tracksNo = 24;    break;
  129.         case '25CH':    *PatternSize = sizeof( struct MODCom) * 64L * 25L;    *tracksNo = 25;    break;
  130.         case '26CH':    *PatternSize = sizeof( struct MODCom) * 64L * 26L;    *tracksNo = 26;    break;
  131.         case '27CH':    *PatternSize = sizeof( struct MODCom) * 64L * 27L;    *tracksNo = 27;    break;
  132.         case '28CH':    *PatternSize = sizeof( struct MODCom) * 64L * 28L;    *tracksNo = 28;    break;
  133.         case '29CH':    *PatternSize = sizeof( struct MODCom) * 64L * 29L;    *tracksNo = 29;    break;
  134.         case '30CH':    *PatternSize = sizeof( struct MODCom) * 64L * 30L;    *tracksNo = 30;    break;
  135.         case '31CH':    *PatternSize = sizeof( struct MODCom) * 64L * 31L;    *tracksNo = 31;    break;
  136.         case '32CH':    *PatternSize = sizeof( struct MODCom) * 64L * 32L;    *tracksNo = 32;    break;
  137.         
  138.         default:
  139.             *PatternSize     = sizeof( struct MODCom) * 64L * 4L;            *tracksNo = 4;
  140.             
  141.             result = true;
  142.             test = 0;
  143.             for( i = 0; i < 15; i++)
  144.             {
  145.                 test += aMOD->fid[i].numWords;
  146.                 if( aMOD->fid[i].fineTune > 0x0F) result = false;
  147.                 
  148.                 if( aMOD->fid[i].loopWords > aMOD->fid[i].numWords) result = false;
  149.             }
  150.             
  151.             if( EOFo != -1)
  152.             {
  153.                 long PatMax = 0;
  154.                 for(i=0; i<128; i++)
  155.                 {
  156.                     if( aMOD->oPointers[i] < 0) aMOD->oPointers[i] = 0;
  157.                     if( aMOD->oPointers[i] > 128) aMOD->oPointers[i] = 0;
  158.                     
  159.                     if( aMOD->oPointers[i] >= PatMax)    PatMax = aMOD->oPointers[i];
  160.                 }
  161.                 PatMax++;
  162.                 
  163.                 if( PatMax * *PatternSize + test > EOFo) result = false;
  164.             }
  165.             
  166.             if( test == 0) result = false;
  167.                         
  168.             if( result) *maxInstru         = 15;
  169.             else *maxInstru             = 0;
  170.         break;
  171.     }
  172. }
  173.  
  174. struct MODCom* GetMODCommand( short position, short whichTracks, short whichPattern, short maxTracks, Ptr PatPtr)
  175. {
  176.     struct MODCom*    myMODCom;
  177.     
  178.     myMODCom =    (struct MODCom*) (PatPtr +
  179.                                 whichPattern * 64L * sizeof( struct MODCom) * maxTracks +
  180.                                 position * sizeof( struct MODCom) * maxTracks +
  181.                                 whichTracks * sizeof( struct MODCom));
  182.     
  183.     return myMODCom;
  184. }
  185.  
  186. OSErr PPConvertMod2Mad( Ptr aMOD,long MODSize, MADPartition    *theMAD, MADDriverSettings* init)
  187. {
  188.     short             i, PatMax, x, tracksNo, z, maxInstru;
  189.     long             sndSize, OffSetToSample, MPatSize, temp, inOutCount;
  190.     Ptr                theInstrument[ 64], MaxPtr;
  191.     long             finetune[16] = 
  192.     {
  193.         8363,    8413,    8463,    8529,    8581,    8651,    8723,    8757,
  194.         7895,    7941,    7985,    8046,    8107,    8169,    8232,    8280
  195.     };
  196.     /**** Variables for MAD File *****/
  197.     Cmd                            *aCmd;
  198.  
  199.     /**** Variables for MOD File *****/
  200.     MODDef                     *theMOD;
  201.     struct MODPat        *PatInt;
  202.     MODDef                    *MODInt;
  203.     struct MODCom        *n;
  204.     /********************************/
  205.     
  206.     theMOD = ((MODDef*) aMOD);
  207.     MaxPtr = (Ptr)((long) theMOD + MODSize);
  208.     
  209.     temp = *((long*)(aMOD + 0x438));        // Signature...
  210.     
  211.     AnalyseSignatureMOD( -1, temp, &maxInstru, &MPatSize, &tracksNo, theMOD);
  212.     
  213.     if( maxInstru == 0)
  214.     {
  215.         return MADFileNotSupportedByThisPlug;    // This file is NOT a Mod file !!!!!! This should NEVER happen !
  216.     }
  217.     else if( maxInstru == 15)                // Old Mods format with 15 instruments
  218.     {
  219.         MODInt = (MODDef*) ( (Ptr) theMOD - (Ptr) 0x1E0);
  220.         PatInt = (struct MODPat*) ((Ptr) MODInt->patterns - (Ptr) 0x4);
  221.         
  222.         PatMax = 0;
  223.         for(i=0; i<128; i++)
  224.         {
  225.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  226.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  227.         
  228.             if( MODInt->oPointers[i] >= PatMax)    PatMax = MODInt->oPointers[i];
  229.         }
  230.         PatMax++;
  231.         
  232.     //    if( MODInt->numPointers > 64) MODInt->numPointers = 64;
  233.     //    for(i=64; i<128; i++) MODInt->oPointers[i] = 0;
  234.         
  235.         OffSetToSample = (long) 0x258 + PatMax * MPatSize;
  236.     }
  237.     else                                    // Mods format with 32 instruments
  238.     {
  239.         MODInt    = theMOD;
  240.         PatInt    = MODInt->patterns;
  241.         
  242.         PatMax = 0;
  243.         for(i=0; i<128; i++)
  244.         {
  245.             if( MODInt->oPointers[i] < 0) MODInt->oPointers[i] = 0;
  246.             if( MODInt->oPointers[i] > 128) MODInt->oPointers[i] = 0;
  247.             
  248.             if( MODInt->oPointers[i] >= PatMax) PatMax = MODInt->oPointers[i];
  249.         }
  250.         PatMax++;
  251.         
  252.         OffSetToSample = (long) 0x43c + PatMax * MPatSize;
  253.     }
  254.     
  255.     for( i = 0; i < maxInstru ; i++)
  256.     {
  257.         theInstrument[ i] = (Ptr) ((long) theMOD + (long) OffSetToSample);
  258.         
  259.         MOT16( &theMOD->fid[ i].numWords);
  260.         MOT16( &theMOD->fid[ i].loopWord);
  261.         MOT16( &theMOD->fid[ i].loopWords);
  262.         
  263.         sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  264.         
  265.         if( theInstrument[i] + sndSize > MaxPtr)
  266.         {
  267.             theMOD->fid[i].numWords = MaxPtr - theInstrument[i];
  268.             theMOD->fid[i].numWords /= 2L;
  269.             
  270.             if( theMOD->fid[i].numWords < 0) theMOD->fid[i].numWords = 0;
  271.                     
  272.             sndSize = ((long) theMOD->fid[i].numWords) * 2L;
  273.         }
  274.         
  275.         OffSetToSample += sndSize;
  276.         
  277.         if( theMOD->fid[i].loopWords > 2 && sndSize > 0)
  278.         {
  279.             if( (long) theMOD->fid[i].loopWord +
  280.                 (long) theMOD->fid[i].loopWords > 
  281.                 (long) theMOD->fid[i].numWords)
  282.             {
  283.                 theMOD->fid[ i].loopWords =    (long) theMOD->fid[i].numWords -
  284.                                             (long) theMOD->fid[i].loopWord;
  285.         
  286.                 if( (long) theMOD->fid[i].loopWord +
  287.                 (long) theMOD->fid[i].loopWords > 
  288.                 (long) theMOD->fid[i].numWords)
  289.                 {
  290.                     theMOD->fid[i].loopWord = 0;
  291.                     theMOD->fid[i].loopWords = 0;
  292.                 }
  293.             }
  294.         }
  295.         else
  296.         {
  297.             theMOD->fid[i].loopWord = 0;
  298.             theMOD->fid[i].loopWords = 0;
  299.         }
  300.     }
  301.     
  302.     /***************************************************************/
  303.     /******** MOD is ready to be converted into MAD File ***********/
  304.     /***************************************************************/
  305.     
  306.     inOutCount = sizeof( MADSpec);
  307.     theMAD->header = (MADSpec*) MADNewPtrClear( inOutCount, init);
  308.     if( theMAD->header == 0L) return MADNeedMemory;
  309.     
  310.     strcpy( theMAD->header->infos, (Ptr) "Converted by PlayerPRO MOD Plug (©Antoine ROSSET <rosset@dial.eunet.ch>)");
  311.     
  312.     theMAD->header->MAD = 'MADH';
  313.     
  314.     for(i=0; i<22; i++) theMAD->header->name[i] = theMOD->NameSignature[i];
  315.     
  316.     theMAD->header->tempo = 125;
  317.     theMAD->header->speed = 6;
  318.     theMAD->header->numPat = PatMax;
  319.     theMAD->header->numPointers = MODInt->numPointers;
  320.     
  321.     for(i=0; i<128; i++) theMAD->header->oPointers[ i] = MODInt->oPointers[ i];
  322.     
  323.     theMAD->header->numChn = tracksNo;
  324.     
  325.     for(i = 0; i < maxInstru; i++)
  326.     {
  327.         for( x = 0; x < 22; x++) theMAD->header->fid[i].name[x] = theMOD->fid[i].Filename[x];
  328.         theMAD->header->fid[i].type = 0;
  329.         theMAD->header->fid[i].volFade = DEFAULT_VOLFADE;
  330.         
  331.         if( theMOD->fid[ i].numWords > 0)
  332.         {
  333.             sData    *curData;
  334.             
  335.             theMAD->header->fid[i].numSamples = 1;
  336.             
  337.             curData = theMAD->sample[ i][ 0] = (sData*) MADNewPtrClear( sizeof( sData), init);
  338.             
  339.             curData->size        = theMOD->fid[i].numWords * 2L;
  340.             curData->loopBeg     = theMOD->fid[i].loopWord*2L;
  341.             curData->loopSize     = theMOD->fid[i].loopWords*2L;
  342.             curData->vol        = theMOD->fid[i].volume;
  343.             curData->c2spd        = finetune[ theMOD->fid[i].fineTune];
  344.             curData->loopType    = 0;
  345.             curData->amp        = 8;
  346.             curData->panning    = 0;
  347.             curData->relNote    = 0;
  348.         //    for( x = 0; x < 22; x++) curData->name[x] = theMOD->fid[ i].Filename[ x];
  349.             
  350.             
  351.             curData->data         = MADNewPtr( curData->size, init);
  352.             if( curData->data == 0L) return MADNeedMemory;
  353.                 
  354.             BlockMove( theInstrument[i], curData->data, curData->size);
  355.         }
  356.         else theMAD->header->fid[ i].numSamples = 0;
  357.     }
  358.     
  359.     for( i = maxInstru; i < MAXINSTRU ; i++)
  360.     {
  361.         theMAD->header->fid[ i].numSamples = 0;
  362.     }
  363.     
  364.     for(i=0; i<theMAD->header->numPat; i++)
  365.     {
  366.         theMAD->partition[ i] = (PatData*) MADNewPtrClear( sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd), init);
  367.         if( theMAD->partition[ i] == 0L) return MADNeedMemory;
  368.         
  369.         theMAD->partition[ i]->header.size         = 64L;
  370.         theMAD->partition[ i]->header.compMode     = 'NONE';
  371.         
  372.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.name[ x] = 0;
  373.         
  374.         theMAD->partition[ i]->header.patBytes = 0L;        theMAD->partition[ i]->header.unused2 = 0L;
  375.     
  376.         MaxPtr = (Ptr) theMAD->partition[ i];
  377.         MaxPtr += sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd);
  378.  
  379.         for(x=0; x<64; x++)
  380.         {
  381.             for(z=0; z<theMAD->header->numChn; z++)
  382.             {
  383.                 aCmd = GetMADCommand(  x,  z, theMAD->partition[ i]);
  384.                 if( (Ptr) aCmd + sizeof( Cmd) > MaxPtr) return -1;
  385.                 
  386.                 /////////////
  387.                 
  388.                 n     =     GetMODCommand(    x,
  389.                                                                 z,
  390.                                                                 i,
  391.                                                                 theMAD->header->numChn,
  392.                                                                 (Ptr) PatInt);
  393.                 
  394.                 
  395.                 
  396.                 aCmd->ins = (n->a&0x10)|(n->c>>4);
  397.                 aCmd->note = FoundNote( (((unsigned short)n->a&0xf)<<8)+n->b);
  398.                 
  399.                 aCmd->cmd = n->c & 0x0F;
  400.                 
  401.                 if( aCmd->cmd == 0x0C)
  402.                 {
  403.                     aCmd->vol    = 0x10 + (n->d);
  404.                     if( aCmd->arg > 0x50) aCmd->vol = 0x50;
  405.                     aCmd->cmd     = 0;
  406.                     aCmd->arg     = 0;
  407.                 }
  408.                 else
  409.                 {
  410.                     aCmd->arg     = n->d;
  411.                     aCmd->vol    = 0xFF;
  412.                 }
  413.             }
  414.         }
  415.     }
  416.     for( i = theMAD->header->numPat; i < MAXPATTERN ; i++) theMAD->partition[ i] = 0L;
  417.     
  418.     return noErr;
  419. }
  420.  
  421. void Convert16to8( Ptr srcPtr, Ptr destPtr, long size)
  422. {
  423. long     i;
  424.  
  425. size /= 2;
  426.  
  427.     for( i = 0; i < size; i ++)
  428.     {
  429.         destPtr[ i] = srcPtr[i*2];
  430.     }
  431. }
  432.  
  433. long ConvertSampleC4SPD( Ptr src, long srcSize, short amp, long srcC4SPD, Ptr dst, long dstC4SPD)
  434. {
  435.     short    *src16 = (short*) src, *dst16 = (short*) dst;
  436.     Ptr        src8 = src, dst8 = dst;
  437.     long    x;
  438.     
  439.     if( amp == 8)
  440.     {
  441.         for( x = 0; x < srcSize; x++)
  442.         {
  443.             dst8[ (x * dstC4SPD) / srcC4SPD] = src8[ x];
  444.         }
  445.     }
  446.     else
  447.     {
  448.         for( x = 0; x < srcSize/2; x++)
  449.         {
  450.             dst16[ (x * dstC4SPD) / srcC4SPD] = src16[ x];
  451.         }
  452.     }
  453.     
  454.     return (srcSize * dstC4SPD) / srcC4SPD;
  455. }
  456.  
  457. Ptr PPConvertMad2Mod( MADPartition *theMAD, MADDriverSettings *init, long *PtrSize)
  458. {
  459.     short                 i, x, z, maxInstru;
  460.     long                 OffSetToSample, InstruSize, *alpha;
  461.     Ptr                    theInstrument[ 64], destPtr;
  462.     Boolean                CheckGoodMod;
  463.     char                redut[4];
  464.     short                MODTuning[ 65] =
  465.                     /*    {    0,
  466.                             1712,1616,1525,1440,1357,1281,1209,1141,1077,1017, 961, 907,
  467.                             856,808,762,720,678,640,604,570,538,508,480,453,
  468.                             428,404,381,360,339,320,302,285,269,254,240,226,
  469.                             214,202,190,180,170,160,151,143,135,127,120,113,
  470.                             107,101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57 };*/
  471.                             
  472.                         {
  473.  
  474.                         // -> Tuning 0
  475.                         
  476.                             1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906,
  477.                             856,808,762,720,678,640,604,570,538,508,480,453,
  478.                             428,404,381,360,339,320,302,285,269,254,240,226,
  479.                             214,202,190,180,170,160,151,143,135,127,120,113,
  480.                             107,101,95,90,85,80,75,71,67,63,60,56
  481.                         };
  482.                             
  483.     /**** Variables for MAD file ****/
  484.     
  485.     Cmd                    *aCmd;
  486.  
  487.     /**** Variables for MOD file ****/
  488.     
  489.     MODDef                 *theMOD;
  490.     struct MODCom        *n;
  491.     /********************************/
  492.  
  493.     maxInstru = 31;
  494.         
  495.     InstruSize = 0;
  496.     for( i = 0; i < maxInstru ; i++)
  497.     {
  498.         if( theMAD->header->fid[ i].numSamples > 0)
  499.         {
  500.             theInstrument[ i]    = theMAD->sample[ i][ 0]->data;
  501.             InstruSize            += theMAD->sample[ i][ 0]->size;
  502.         }
  503.     }
  504.     
  505.     /******** MAD is ready to be converted **********/
  506.     /******** Copy information in the MOD file    ***/
  507.     
  508.     *PtrSize = 0x43c + InstruSize + theMAD->header->numChn * 64L * theMAD->header->numPat * sizeof( struct MODCom);
  509.     
  510.     theMOD = (MODDef*) MADNewPtr( *PtrSize, init);
  511.     if( theMOD == 0L) return 0L;
  512.     
  513.     theMOD->longFmtSignature = 'M.K.';
  514.     if( theMAD->header->numChn > 4)
  515.     {
  516.         if( theMAD->header->numChn >= 10)
  517.         {
  518.             redut[0] = 0x30 + (theMAD->header->numChn / 10);
  519.             redut[1] = 0x30 + (theMAD->header->numChn - 10);
  520.             redut[2] = 'C';
  521.             redut[3] = 'H';
  522.         }
  523.         else
  524.         {
  525.             redut[0] = 0x30 + theMAD->header->numChn;
  526.             redut[1] = 'C';
  527.             redut[2] = 'H';
  528.             redut[3] = 'N';
  529.         }
  530.         
  531.         alpha = (long*) redut;
  532.         
  533.         theMOD->longFmtSignature = *alpha;
  534.     }
  535.     
  536.     for(i=0; i<20; i++) theMOD->NameSignature[i] = theMAD->header->name[i];
  537.     
  538.     CheckGoodMod = false;
  539.     theMOD->numPointers = theMAD->header->numPointers;
  540.     for(i=0; i<128; i++)
  541.     {
  542.         theMOD->oPointers[ i] = theMAD->header->oPointers[ i];
  543.         if( theMOD->oPointers[ i] == theMAD->header->numPat - 1) CheckGoodMod = true;
  544.     }
  545.     if( !CheckGoodMod) theMOD->oPointers[ theMOD->numPointers + 1] = theMAD->header->numPat - 1;
  546.     
  547.     for(i=0; i<maxInstru; i++)
  548.     {
  549.         if( theMAD->header->fid[ i].numSamples > 0)
  550.         {
  551.             sData    *curData = theMAD->sample[ i][ 0];
  552.             short    temp;
  553.         
  554.             for( x = 0; x < 22; x++) theMOD->fid[i].Filename[x] = theMAD->header->fid[i].name[x];
  555.             
  556.             if( curData->size/2L > 0xFFFFUL) theMOD->fid[i].numWords = 0xFFFFUL;
  557.             else theMOD->fid[i].numWords = (short) (curData->size / 2L);
  558.             
  559.             temp = (curData->c2spd - NOFINETUNE) / 50;
  560.             if( temp < 0) temp += 16;
  561.             
  562.             theMOD->fid[i].fineTune        = temp;
  563.             
  564.             theMOD->fid[i].volume         = curData->vol;
  565.             theMOD->fid[i].loopWord     = curData->loopBeg / 2L;
  566.             theMOD->fid[i].loopWords     = curData->loopSize / 2L;
  567.             
  568.             if( curData->c2spd > 8757 || curData->c2spd < 7895)
  569.             {
  570.                 theMOD->fid[i].fineTune = 0;
  571.                 theMOD->fid[i].loopWord = ((curData->loopBeg / 2L) * 8363L) / curData->c2spd;
  572.                 theMOD->fid[i].loopWords = ((curData->loopSize / 2L) * 8363L) / curData->c2spd;
  573.                 theMOD->fid[i].numWords = (theMOD->fid[i].numWords * 8363L) / curData->c2spd;
  574.             }
  575.         }
  576.         else
  577.         {
  578.             for( x = 0; x < 22; x++) theMOD->fid[i].Filename[x] = 0;
  579.             
  580.             theMOD->fid[i].numWords     = 0;
  581.             theMOD->fid[i].fineTune     = 0;
  582.             theMOD->fid[i].volume         = 64;
  583.             theMOD->fid[i].loopWord     = 0;
  584.             theMOD->fid[i].loopWords     = 0;
  585.         }
  586.     }
  587.     
  588.     InstruSize = 0L;
  589.     
  590.     OffSetToSample = (long) 0x43c + theMAD->header->numPat * sizeof( struct MODCom) * 64L * theMAD->header->numChn;
  591.     
  592.     for(i=0; i<maxInstru; i++)
  593.     {
  594.         sData    *curData = theMAD->sample[ i][ 0];
  595.         
  596.         destPtr = (Ptr) ((long) theMOD + (long) OffSetToSample + (long) InstruSize);
  597.         
  598.         if( curData->c2spd > 8757 || curData->c2spd < 7895)
  599.         {
  600.             ConvertSampleC4SPD( theInstrument[ i], curData->size, curData->amp, curData->c2spd, destPtr, 8363);
  601.         }
  602.         else
  603.         {
  604.             BlockMove( theInstrument[i], destPtr, (long) (theMOD->fid[i].numWords) * 2L);
  605.         }
  606.         
  607.         if( theMOD->fid[i].numWords > 0)
  608.         {
  609.             if( curData->amp == 16)
  610.             {
  611.                 Convert16to8(    destPtr,
  612.                                 destPtr, 
  613.                                 (long) (theMOD->fid[i].numWords) * 2L);
  614.                 
  615.                 theMOD->fid[i].loopWord /=2;
  616.                 theMOD->fid[i].loopWords /=2;
  617.                 theMOD->fid[i].numWords /= 2;
  618.             }
  619.         }
  620.         
  621.         InstruSize += (long) (theMOD->fid[i].numWords) * 2L;
  622.     }
  623.     
  624.     for(i=0; i<theMAD->header->numPat; i++)
  625.     {
  626.         for(x=0; x < 64; x++)
  627.         {
  628.             for(z=0; z < theMAD->header->numChn; z++)
  629.             {
  630.                 short        note;
  631.                 
  632.                 aCmd         = GetMADCommand(     x,
  633.                                                                     z,
  634.                                                                     theMAD->partition[ i]);
  635.                 
  636.                 n             = GetMODCommand(    x,
  637.                                                                     z,
  638.                                                                     i,
  639.                                                                     theMAD->header->numChn,
  640.                                                                     (Ptr) theMOD->patterns);
  641.                 
  642.                 n->a = aCmd->ins & 0xF0;
  643.                 n->c = (aCmd->ins & 0x0F)<<4;
  644.                 
  645.                 if( aCmd->note != 0xFF && aCmd->note != 0xFE)
  646.                 {
  647.                     short curNote;
  648.                     
  649.                     if( aCmd->ins != 0) curNote = aCmd->note + theMAD->sample[ aCmd->ins-1][ 0]->relNote;
  650.                     else curNote = aCmd->note;
  651.                     
  652.                     curNote -= 24;
  653.                     
  654.                     if( curNote > 0 && curNote < 65) curNote = MODTuning[ curNote];
  655.                     else curNote = 0;
  656.                     
  657.                     n->b = curNote & 0xFF;
  658.                     n->a = n->a + (curNote>>8);
  659.                 }
  660.                 else
  661.                 {
  662.                     n->b = 0;
  663.                     n->a = n->a + 0x0;
  664.                 }
  665.                 
  666.                 if( aCmd->vol != 0xFF && aCmd->cmd == 0 && aCmd->arg == 0)
  667.                 {
  668.                     if( aCmd->vol >= 0x10 && aCmd->vol <= 0x50)
  669.                     {
  670.                         n->c = n->c + 0xC;
  671.                         n->d = aCmd->vol - 0x10;
  672.                     }
  673.                 }
  674.                 else
  675.                 {
  676.                     n->c = n->c + (aCmd->cmd & 0x0F);
  677.                     n->d = aCmd->arg;
  678.                 }
  679.             }
  680.         }
  681.     }
  682.     
  683.     return( (Ptr) theMOD);
  684. }
  685.  
  686. OSErr ExtractMODInfo( PPInfoRec *info, Ptr AlienFile)
  687. {
  688.     MODDef    *myMOD = ( MODDef*) AlienFile;
  689.     long    PatternSize;
  690.     short    i;
  691.     short    maxInstru;
  692.     
  693.     /*** Signature ***/
  694.     
  695.     info->signature = myMOD->longFmtSignature;
  696.     
  697.     /*** Internal name ***/
  698.     
  699.     myMOD->NameSignature[ 19] = '\0';
  700.     strcpy( info->internalFileName, myMOD->NameSignature);
  701.     
  702.     /*** Check MOD Type ***/
  703.     
  704.     AnalyseSignatureMOD( -1, info->signature, &maxInstru, &PatternSize, &info->totalTracks, myMOD);
  705.     if( maxInstru == 0)
  706.     {
  707.         return MADFileNotSupportedByThisPlug;
  708.     }
  709.     else if( maxInstru == 15)    // Old mod format
  710.     {
  711.         info->signature = '----';
  712.         myMOD = (MODDef*) ((Ptr) myMOD - (Ptr) 0x1E0);
  713.     }
  714.     
  715.     /*** Total Patterns ***/
  716.     
  717.     info->totalPatterns = 0;
  718.     for( i = 0; i < 128; i++)
  719.     {
  720.         if( myMOD->oPointers[ i] >= info->totalPatterns)    info->totalPatterns = myMOD->oPointers[ i];
  721.     }
  722.     info->totalPatterns++;
  723.     
  724.     /*** Partition Length ***/
  725.     
  726.     info->partitionLength = myMOD->numPointers;
  727.     
  728.     /*** Total Instruments ***/
  729.     
  730.     for( i = 0, info->totalInstruments = 0; i < maxInstru ; i++)
  731.     {
  732.         if( myMOD->fid[ i].numWords > 5) info->totalInstruments++;
  733.     }
  734.     
  735.     strcpy( info->formatDescription, "MOD Plug");
  736.     
  737.     return noErr;
  738. }
  739.  
  740. OSErr TestMODFile( Ptr AlienFile, long EOFo)
  741. {
  742.     short        maxInstru;
  743.     long        PatternSize;
  744.     short        tracksNo;
  745.     
  746.     AnalyseSignatureMOD( EOFo, *((long*)(AlienFile + 0x438)), &maxInstru, &PatternSize, &tracksNo, (MODDef*) AlienFile);
  747.     
  748.     if( maxInstru == 0) return MADFileNotSupportedByThisPlug;
  749.     else return noErr;
  750. }
  751.  
  752. #ifndef _MAC_H
  753. EXP OSErr FillPlug( PlugInfo *p)        // Function USED IN DLL - For PC & BeOS
  754. {
  755.     strcpy( p->type,         ".MOD");
  756.     strcpy( p->MenuName,     "MOD Files");
  757.     p->mode    =    'EXIM';
  758.     
  759.     return noErr;
  760. }
  761. #endif
  762.  
  763. /*****************/
  764. /* MAIN FUNCTION */
  765. /*****************/
  766. EXP OSErr main( OSType order, Ptr AlienFileName, MADPartition *MadFile, PPInfoRec *info, MADDriverSettings *init)
  767. {
  768.     OSErr        myErr;
  769.     Ptr            AlienFile;
  770.     long        sndSize;
  771.     UNFILE    iFileRefI;
  772.     
  773.     #ifdef _MAC_H
  774.         #ifndef powerc
  775.             long    oldA4 = SetCurrentA4();            //this call is necessary for strings in 68k code resources
  776.         #endif
  777.     #endif
  778.     
  779.     myErr = noErr;
  780.     
  781.     switch( order)
  782.     {
  783.         case 'IMPL':
  784.             iFileRefI = iFileOpen( AlienFileName);
  785.             if( iFileRefI)
  786.             {
  787.                 sndSize = iGetEOF( iFileRefI);
  788.                 
  789.                 // ** MEMORY Test Start
  790.                 AlienFile = MADNewPtr( sndSize * 2L, init);
  791.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  792.                 // ** MEMORY Test End
  793.                 
  794.                 else
  795.                 {
  796.                     DisposPtr( AlienFile);
  797.                     
  798.                     AlienFile = MADNewPtr( sndSize, init);
  799.                     iRead( sndSize, AlienFile, iFileRefI);
  800.                     
  801.                     myErr = TestMODFile( AlienFile, sndSize);
  802.                     if( myErr == noErr)
  803.                     {
  804.                         myErr = PPConvertMod2Mad( AlienFile, sndSize, MadFile, init);
  805.                     }
  806.                     
  807.                     DisposPtr( AlienFile);    AlienFile = 0L;
  808.                 }
  809.                 iClose( iFileRefI);
  810.             }
  811.             else myErr = MADReadingErr;
  812.         break;
  813.         
  814.         case 'TEST':
  815.             iFileRefI = iFileOpen( AlienFileName);
  816.             if( iFileRefI)
  817.             {
  818.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  819.                 
  820.                 AlienFile = MADNewPtr( sndSize, init);
  821.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  822.                 else
  823.                 {
  824.                     iRead( sndSize, AlienFile, iFileRefI);
  825.                     
  826.                     sndSize = iGetEOF( iFileRefI);
  827.                     
  828.                     myErr = TestMODFile( AlienFile, sndSize);
  829.                     
  830.                     DisposPtr( AlienFile);    AlienFile = 0L;
  831.                 }
  832.                 iClose( iFileRefI);
  833.             }
  834.             else myErr = MADReadingErr;
  835.         break;
  836.         
  837.         case 'EXPL':
  838.             AlienFile = PPConvertMad2Mod( MadFile, init, &sndSize);
  839.             
  840.             if( AlienFile != 0L)
  841.             {
  842.                 iFileCreate( AlienFileName, 'STrk');
  843.                 iFileRefI = iFileOpen( AlienFileName);
  844.                 if( iFileRefI)
  845.                 {
  846.                     iWrite( sndSize, AlienFile, iFileRefI);
  847.                     iClose( iFileRefI);
  848.                 }
  849.                 DisposPtr( AlienFile);    AlienFile = 0L;
  850.             }
  851.             else myErr = MADReadingErr;
  852.         break;
  853.         
  854.         case 'INFO':
  855.             iFileRefI = iFileOpen( AlienFileName);
  856.             if( iFileRefI)
  857.             {
  858.                 info->fileSize = iGetEOF( iFileRefI);
  859.                 
  860.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  861.                 
  862.                 AlienFile = MADNewPtr( sndSize, init);
  863.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  864.                 else
  865.                 {
  866.                     iRead( sndSize, AlienFile, iFileRefI);
  867.                     myErr = ExtractMODInfo( info, AlienFile);
  868.                     
  869.                     DisposPtr( AlienFile);    AlienFile = 0L;
  870.                 }
  871.                 iClose( iFileRefI);
  872.             }
  873.             else myErr = MADReadingErr;
  874.         break;
  875.         
  876.         default:
  877.             myErr = MADOrderNotImplemented;
  878.         break;
  879.     }
  880.     
  881.     #ifdef _MAC_H
  882.     #ifndef powerc
  883.         SetA4( oldA4);
  884.     #endif
  885.     #endif
  886.     
  887.     return myErr;
  888. }